import os
import traceback

from flask import Flask, send_from_directory
from flask_cors import *

from flask import request
from sqlalchemy import func

from database.db import Group, Nodes, Edges
from database.exts import db
import pymysql

pymysql.install_as_MySQLdb()

app = Flask(__name__)

CORS(app, supports_credentials=True)

class Config(object):
    """配置参数"""
    # 设置连接数据库的URL
    user = 'root'
    password = 'buAAfYta901022'
    database = 'atlas'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@39.97.209.211:3306/%s' % (user, password, database)

    # 设置sqlalchemy自动更跟踪数据库
    SQLALCHEMY_TRACK_MODIFICATIONS = True
    # 防止超时
    SQLALCHEMY_POOL_RECYCLE = 10
    SQLALCHEMY_POOL_SIZE = 30

    # 查询时会显示原始SQL语句
    app.config['SQLALCHEMY_ECHO'] = True

    # 禁止自动提交数据处理
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = False


@app.route('/')
def hello_world():
    groups = Group.query.all()
    print(groups[0].id)
    print(groups[0].group_name)
    id = int(db.session.query(func.max(Nodes.id)).scalar())
    print("max_id:", id)
    return 'Hello World!'


@app.route('/all')
def all():
    # 返回全部nodes节点信息，以及edges边信息
    try:
        nodes = Nodes.query.all()
        edges = Edges.query.all()
        nodes_list = []
        edges_list = []
        for i in range(len(nodes)):
            temp = {}
            temp["id"] = nodes[i].id
            temp["node_name"] = nodes[i].node_name
            temp["child_num"] = nodes[i].child_num
            temp["group_id"] = nodes[i].group_id
            temp["ncpus"] = nodes[i].ncpus
            temp["ngpus"] = nodes[i].ngpus
            temp["queue"] = nodes[i].queue
            temp["nnodes"] = nodes[i].nnodes
            temp["node_mem"] = nodes[i].node_mem
            temp["node_cpus"] = nodes[i].node_cpus
            temp["node_cputype"] = nodes[i].node_cputype
            temp["node_storage"] = nodes[i].node_storage
            temp["node_type"] = nodes[i].node_type
            temp["node_os"] = nodes[i].node_os
            temp["sccenter_name"] = nodes[i].sccenter_name
            temp["sccenter_location"] = nodes[i].sccenter_location
            temp["sc_user"] = nodes[i].sc_user
            temp["software"] = nodes[i].software
            temp["software_version"] = nodes[i].software_version
            temp["software_type"] = nodes[i].software_type
            temp["software_outline"] = nodes[i].software_outline
            temp["service_type"] = nodes[i].service_type
            temp["inputfiles_m"] = nodes[i].inputfiles_m
            temp["inputdirs_o"] = nodes[i].inputdirs_o
            temp["inputfiles_o"] = nodes[i].inputfiles_o
            temp["limit_time"] = nodes[i].limit_time
            temp["outpath"] = nodes[i].outpath
            temp["other"] = nodes[i].other
            nodes_list.append(temp)

        for i in range(len(edges)):
            temp = {}
            temp["id"] = edges[i].id
            temp["src"] = edges[i].src
            temp["dst"] = edges[i].dst
            edges_list.append(temp)

        return {"msg": "success", "code": 0, "nodes": nodes_list, "edges": edges_list}
    except Exception as e:
        return {"msg": "error", "code": 1, "nodes": [], "edges": []}


@app.route('/search')
def search():
    # 实现模糊搜索
    try:
        keyword = request.args.get('keyword')
        nodes = Nodes.query.filter(Nodes.node_name.like('%' + keyword + '%')).all()
        nodes_id_list = []
        if len(nodes) == 0:
            return {"msg": "not found", "code": 0, "nodes_id": []}
        for i in range(len(nodes)):
            temp = {}
            temp["id"] = nodes[i].id
            nodes_id_list.append(temp)
        return {"msg": "success", "code": 0, "nodes_id": nodes_id_list}
    except Exception as e:
        return {"msg": "error", "code": 1, "nodes_id": []}


@app.route('/add', methods=['POST'])
def add():
    # 添加节点
    try:
        src_id = int(request.json.get('src', 1))
        data = request.json.get('data')

        print(src_id)

        # 准备：先把父节点查出来
        src_node = Nodes.query.filter_by(id=src_id).first()
        # 准备：找出最大的id，新增的node就是最大id加一，为了最后一并提交，因此不能使用自增的id
        max_id = int(db.session.query(func.max(Nodes.id)).scalar())
        # print("max_id:", id)
        # 首先建立node
        new_id = max_id + 1
        new_node = Nodes()
        new_node.id = new_id
        new_node.node_name = data["node_name"]
        new_node.child_num = 0
        new_node.group_id = src_node.group_id
        new_node.ncpus = data["ncpus"]
        new_node.ngpus = data["ngpus"]
        new_node.queue = data["queue"]
        new_node.nnodes = data["nnodes"]
        new_node.node_mem = data["node_mem"]
        new_node.node_cpus = data["node_cpus"]
        new_node.node_cputype = data["node_cputype"]
        new_node.node_storage = data["node_storage"]
        new_node.node_type = data["node_type"]
        new_node.node_os = data["node_os"]
        new_node.sccenter_name = data["sccenter_name"]
        new_node.sccenter_location = data["sccenter_location"]
        new_node.sc_user = data["sc_user"]
        new_node.software = data["software"]
        new_node.software_version = data["software_version"]
        new_node.software_type = data["software_type"]
        new_node.software_outline = data["software_outline"]
        new_node.service_type = data["service_type"]
        new_node.inputfiles_m = data["inputfiles_m"]
        new_node.inputdirs_o = data["inputdirs_o"]
        new_node.inputfiles_o = data["inputfiles_o"]
        new_node.limit_time = data["limit_time"]
        new_node.outpath = data["outpath"]
        new_node.other = data["other"]

        # 判断添加的是否是二级节点
        if src_id == 0:
            group_id = int(db.session.query(func.max(Group.id)).scalar()) + 1
            # 新建一个group组
            group = Group()
            group.id = group_id
            group.group_name = data["node_name"]
            db.session.add_all([group])
            # 修改新增节点的组
            new_node.group_id = group_id

        db.session.add_all([new_node])

        # 其次，建立edges
        edge = Edges()
        edge.id = int(db.session.query(func.max(Edges.id)).scalar()) + 1
        edge.src = src_id
        edge.dst = new_id
        db.session.add_all([edge])

        # 最后，父节点增加一个子节点数量
        src_node.child_num += 1

        # 一并提交
        db.session.commit()

        return {"msg": "success", "code": 0}

    except Exception as e:
        print("#####")
        traceback.print_exc()
        print("#####")
        return {"msg": "error", "code": 1}


@app.route('/delete')
def delete():
    # 实现节点删除
    try:
        node_id = int(request.args.get('id'))
        del_node = Nodes.query.filter_by(id=node_id).first()
        if del_node.child_num > 0:
            return {"msg": "can not delete, it has child nodes", "code": 1}
        # 先删除节点
        db.session.delete(del_node)
        # 删除边
        edge = Edges.query.filter_by(dst=node_id).first()
        src = edge.src
        db.session.delete(edge)
        # 父节点的child num--
        src_node = Nodes.query.filter_by(id=src).first()
        src_node.child_num -= 1
        # 一并提交
        db.session.commit()

        return {"msg": "success", "code": 0}
    except Exception as e:
        print("#####")
        traceback.print_exc()
        print("#####")
        return {"msg": "error", "code": 1}


@app.route('/download')
def download():
    # 实现节点下载
    try:
        node_id = int(request.args.get('id'))
        node = Nodes.query.filter_by(id=node_id).first()
        if node.file_name == "" or node.file_name is None:
            return {"msg": "本节点不支持下载附件", "code": 1}
        dirpath = os.path.join(app.root_path, 'static/file')
        return send_from_directory(dirpath, node.file_name, as_attachment=True)
    except Exception as e:
        print("#####")
        traceback.print_exc()
        print("#####")
        return {"msg": "error", "code": 1}


@app.route('/view')
def file_view():
    # 实现节点下载
    try:
        node_id = int(request.args.get('id'))
        node = Nodes.query.filter_by(id=node_id).first()
        if node.file_name == "" or node.file_name is None:
            return {"msg": "本节点无预览附件", "code": 1}
        file_str = node.file_str
        return {"msg": "success", "code": 0, "file_str": file_str}
    except Exception as e:
        print("#####")
        traceback.print_exc()
        print("#####")
        return {"msg": "error", "code": 1}


# 读取配置
app.config.from_object(Config)
# 载入数据库
db.init_app(app)

if __name__ == '__main__':

    app.run(host='0.0.0.0', port=5000)
